﻿using Core.Log;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core.Utility.Helper
{
    /// <summary>
    /// 用于某些方法需要多次尝试执行。保证返回成功
    /// </summary>
    public static class RetryHelper
    {
        /// <summary>
        /// 匿名方法
        /// </summary>
        /// <param name="func">匿名方法，执行成功不在执行返回ture，若方法体出现异常，将被捕获，并返回false</param>
        /// <param name="retryCount">递归次数</param>
        /// <returns>返回匿名方法中返回的值，匿名方法执行失败|异常，或递归到递归次数上限，返回false</returns>
        public static bool RetryFunc(Func<bool> func, uint retryCount = 1)
        {
            uint exeCount = 0;
            if(retryCount <= 0)
            {
                retryCount = 1;
            }
            bool result;
            do
            {
                exeCount++;
                try
                {
                    result = func();
                }
                catch (Exception ex)
                {                    
                    result = false;
                    AppTrace.Logger.LogError(ex, $"调用方法：{func.Method.Name} 出现异常，已执行 {exeCount} / {retryCount + exeCount}  次", new { 消息来源 = "RetryHelper.RetryFunc", 附加信息 = "重试方法调用出现异常" });                    
                }
            }
            while (!result && retryCount-- > 1);
            if(result == false )
            {
                AppTrace.Logger.LogError($"调用方法：{func.Method.Name} 执行失败，已执行 {exeCount} / {retryCount + exeCount}  次", new { 消息来源 = "RetryHelper.RetryFunc", 附加信息 = "重试方法调用失败" });
            }
            return result;
        }

        /// <summary>
        /// 匿名方法
        /// </summary>
        /// <param name="funcAsync">匿名方法，执行成功不在执行返回ture，若方法体出现异常，将被捕获，并返回false</param>
        /// <param name="retryCount">递归次数</param>
        /// <returns>返回匿名方法中返回的值，匿名方法执行失败|异常，或递归到递归次数上限，返回false</returns>
        public static async Task<bool> RetryFuncAsync(Func<Task<bool>> funcAsync, uint retryCount = 1)
        {
            uint exeCount = 0;
            if (retryCount <= 0)
            {
                retryCount = 1;
            }
            bool result;
            do
            {
                exeCount++;
                try
                {
                    result =  await funcAsync();
                }
                catch (Exception ex)
                {
                    result = false;
                    AppTrace.Logger.LogError(ex, $"调用方法：{funcAsync.Method.Name} 出现异常，已执行 {exeCount} / {retryCount + exeCount}  次", new { 消息来源 = "RetryHelper.RetryFunc", 附加信息 = "重试方法调用出现异常" });
                }
            }
            while (!result && retryCount-- > 1);
            if (result == false)
            {
                AppTrace.Logger.LogError($"调用方法：{funcAsync.Method.Name} 执行失败，已执行 {exeCount} / {retryCount + exeCount}  次", new { 消息来源 = "RetryHelper.RetryFunc", 附加信息 = "重试方法调用失败" });
            }
            return result;
        }
    }
}
